/* Primary functionality for the Directory Gadget. */
var RiseVision = RiseVision || {};
RiseVision.DirectorySettings = {};
RiseVision.Directory = {};

/* Settings Start */
RiseVision.DirectorySettings = function() {
    this.settings = new RiseVision.Common.Settings();
}
//Populate settings from saved values.
RiseVision.DirectorySettings.prototype.initSettings = function() {
    var self = this;
        
    //Add event handlers.
    $("#cardImage").on("blur", function(event) {
	var cardImage = $(this).val();
    
	if (cardImage && (isNaN(cardImage))) {	    
	    $("li.cardImage").show();
	}
	else {
	    $("li.cardImage").hide();
	}
    });
    
    $("#cardTitle").on("blur", function(event) {
	var cardTitle = $(this).val();
	
	if (cardTitle && (isNaN(cardTitle))) {
	    $("li.cardTitle").show();
	}
	else {
	    $("li.cardTitle").hide();
	}
    });
    
    $("#cardSubtitle").on("blur", function(event) {
	var cardSubtitle = $(this).val();
	
	if (cardSubtitle && (isNaN(cardSubtitle))) {
	    $("li.cardSubtitle").show();
	}
	else {
	    $("li.cardSubtitle").hide();
	}
    });
    
    $("#cardDetail").on("blur", function(event) {
	var cardDetail = $(this).val();
	
	if (cardDetail && (isNaN(cardDetail))) {
	    $("li.cardDetail").show();
	}
	else {
	    $("li.cardDetail").hide();
	}
    });
    
    $(".colorPicker").on("click", function(event) {
	directory.showColorPicker($(this).data("for"));
    });
    
    $(".fontSelector").on("click", function(event) {
	directory.showFontSelector($(this).data("for"));
    });
    
    $("#scrollDirection").on("change", function(event) {
	if ($(this).val() == "none") {
	    $("li.scroll").hide();
	}
	else {
	    $("li.scroll").show();
	}
    });
    
    $("#scrollBy").on("change", function(event) {
	if ($(this).val() == "continuous") {
	    $("li.scrollHold").hide();
	}
	else {
	    $("li.scrollHold").show();
	}
    });
    
    $("#nav").on("change", function(event) {
	var nav = $(this).val();
    
	if (nav == "none") {
	    $("li.nav").hide();
	}
	else {
	    $("li.nav").show();
	}
	
	if ((nav == "left") || (nav == "right")) {
	    $("li.horizontal").hide();
	}
	else {
	    $("li.horizontal").show();
	}
    });
    
    $("#colCount").on("change", function(event) {
	directory.buildColumnsUI();
    });
    
    $("#showCard").on("click", function(event) {
	if ($(this).is(":checked")) {
	    $("li.card").show();
	}
	else {
	    $("li.card").hide();
	}
    });
    
    $("#cardUseDefault").on("click", function(event) {
	if ($(this).is(":checked")) {
	    $("li.cardLayoutURL").hide();
	}
	else {
	    $("li.cardLayoutURL").show();
	}
    });
    
    $("#useDefault").on("click", function(event) {
	if ($(this).is(":checked")) {
	    $("li.layoutURL").hide();
	}
	else {
	    $("li.layoutURL").show();
	}
    });
    
    //If Data URL has a value, then this Gadget has been saved before. Restore the saved settings.
    if (prefs.getString("url")) {
	$("#url").val(prefs.getString("url"));
	$("#refresh").val(prefs.getInt("refresh"));
	$("#imageCol").val(prefs.getString("imageCol"));	
	$("#scrollDirection").val(prefs.getString("scrollDirection"));
	$("#scrollBy").val(prefs.getString("scrollBy"));
	$("#scrollHold").val(prefs.getInt("scrollHold"));
	$("#scrollSpeed").val(prefs.getString("scrollSpeed"));
	$("#scrollResumes").val(prefs.getInt("scrollResumes"));	
	$("#rowPadding").val(prefs.getInt("rowPadding"));
	$("#nav").val(prefs.getString("nav"));
	$("#showAll").val(prefs.getInt("showAll"));
	$("#navMargin").val(prefs.getInt("navMargin"));		
	$("#rowHeight").val(prefs.getInt("rowHeight"));
	$("#colPadding").val(prefs.getInt("colPadding"));
	$("#colCount").val(prefs.getInt("colCount"));
	$("#showCard").attr("checked", prefs.getBool("showCard"));	
	$("#useDefault").attr("checked", prefs.getBool("useDefault"));
	$("#layoutURL").val(prefs.getString("layoutURL"));
	
	//Populate colors and show color as background of text box.
	this.populateColor($("#rowColor"), prefs.getString("rowColor"));
	this.populateColor($("#altRowColor"), prefs.getString("altRowColor"));
	this.populateColor($("#bgColor"), prefs.getString("bgColor"));
	this.populateColor($("#navColor"), prefs.getString("navColor"));
	this.populateColor($("#navBgColor"), prefs.getString("navBgColor"));
	this.populateColor($("#headingColor"), prefs.getString("headingColor"));;
	this.populateColor($("#headingBgColor"), prefs.getString("headingBgColor"));
	this.populateColor($("#headingSortColor"), prefs.getString("headingSortColor"));	
    }
    
    //Build UI for columns before populating.
    $("#colCount").trigger("change");
    
    //Request additional parameters from the Viewer.
    gadgets.rpc.call("", "rscmd_getAdditionalParams", function(result) {
	if (result) {
	    result = JSON.parse(result);
	    
	    //Populate fonts.
	    $("#data_font-style").text(result["data_font"]);
	    $("#data_font-style").data("css", result["data_font-style"]);
	    $("#nav_font-style").text(result["nav_font"]);
	    $("#nav_font-style").data("css", result["nav_font-style"]);	    
	    $("#heading_font-style").text(result["heading_font"]);
	    $("#heading_font-style").data("css", result["heading_font-style"]);
	
	    //Populate card settings.
	    $("#cardLocation").val(result["cardLocation"]);
	    $("#cardWidth").val(result["cardWidth"]);
	    $("#cardTimeout").val(result["cardTimeout"]);
	    $("#cardBorder").attr("checked", result["cardBorder"]);
	    $("#cardImage").val(result["cardImage"]);
	    $("#cardImageAlign").val(result["cardImageAlign"]);
	    $("#cardImageWidth").val(result["cardImageWidth"]);
	    $("#cardImagePadding").val(result["cardImagePadding"]);
	    $("#cardTitle").val(result["cardTitle"]);
	    $("#cardTitle_font-style").text(result["cardTitle_font"]);
	    $("#cardTitle_font-style").data("css", result["cardTitle_font-style"]);
	    $("#cardTitlePadding").val(result["cardTitlePadding"]);	    
	    $("#cardSubtitle").val(result["cardSubtitle"]);
	    $("#cardSubtitle_font-style").text(result["cardSubtitle_font"]);
	    $("#cardSubtitle_font-style").data("css", result["cardSubtitle_font-style"]);
	    $("#cardSubtitlePadding").val(result["cardSubtitlePadding"]);	    
	    $("#cardDetail").val(result["cardDetail"]);
	    $("#cardDetail_font-style").text(result["cardDetail_font"]);
	    $("#cardDetail_font-style").data("css", result["cardDetail_font-style"]);
	    $("#cardDetailPadding").val(result["cardDetailPadding"]);
	    $("#cardUseDefault").attr("checked", result["cardUseDefault"]);
	    $("#cardLayoutURL").val(result["cardLayoutURL"]);
	    
	    //Populate colors and show color as background of text box.
	    self.populateColor($("#cardBgColor"), result["cardBgColor"]);
	    self.populateColor($("#closeBorderColor"), result["closeBorderColor"]);
	    self.populateColor($("#closeFillColor"), result["closeFillColor"]);
	
	    //Populate columns.
	    for (var i = 0; i < parseInt($("#colCount").val()); i++) {
		self.initColumns(i + 1, result.columns[i]);
	    }
	}
	
	//Manually trigger event handlers so that the visibility of fields can be set.
	$("#cardImage").trigger("blur");
	$("#cardTitle").trigger("blur");
	$("#cardSubtitle").trigger("blur");
	$("#cardDetail").trigger("blur");
	$("#scrollDirection").trigger("change");
	$("#scrollBy").trigger("change");
	$("#nav").trigger("change");	
	$("#showCard").triggerHandler("click");
	$("#cardUseDefault").triggerHandler("click");
	$("#useDefault").triggerHandler("click");
	$("#settings").show();
    });
}
RiseVision.DirectorySettings.prototype.populateColor = function($element, color) {
    $element.val(color);
    $element.css("background-color", color);
}
RiseVision.DirectorySettings.prototype.initColumns = function(index, column) {
    $("#column" + index).val(column.column);
    $("#alignment" + index).val(column.alignment);
    $("#width" + index).val(column.width);
    $("#headerText" + index).val(column.header);
}
//Add UI for column format settings.
RiseVision.DirectorySettings.prototype.buildColumnsUI = function() {
    var colCount = parseInt($("#colCount").val()),
	conditionalCount = $(".column").length;
	
    //Hide all fields related to column formatting.
    if (isNaN(colCount) || colCount == 0) {
	$(".formatting").hide();
    }
    else {
	//Column formatting fields have already been created, so show them.
	if (colCount == conditionalCount) {
	    $(".formatting").show();
	}
	//There are enough settings, so show the appropriate number of them.
	else if (colCount < conditionalCount) {
	    $(".formatting").hide();
	    $(".formatting:lt(" + colCount + ")").show();
	}
	//Not enough conditional column formatting settings.
	else {
	    //Show all existing settings.
	    $(".formatting").show();
	    
	    for (var i = conditionalCount + 1; i <= colCount; i++) {
		var li = document.createElement("li"),
		    ol = document.createElement("ol");
		    
		    ol.setAttribute("class", "formatting drillDown");
		    
		    $(ol)
			.append($("<li></li>")
			    .append("<label for='column" + i + "'>" +
				"<a href='#' class='tooltip'>Column*:<span>Column of the spreadsheet that the formatting should apply to (e.g. A or AW)</span></a>" +
				"</label>")
			    .append("<input id='column" + i + "' name='column" + i + "' type='text' class='column short' />"))
			.append($("<li></li>")
			    .append("<label for='alignment" + i + "'>Alignment:</label>")
			    .append("<select id='alignment" + i + "' name='alignment" + i + "' class='alignment short'>" +
				"<option value='left' selected='selected'>Left</option>" +
				"<option value='center'>Center</option>" +
			     "<option value='right'>Right</option>" +
				"</select>"))
			.append($("<li></li>")
			    .append("<label for='width" + i + "'>Width (pixels):</label>")
			    .append("<input id='width" + i + "' name='width" + i + "' type='text' class='width short' value='100' />"))
			.append($("<li></li>")
			    .append("<label for='headerText" + i + i + "'>" +
				"<a href='#' class='tooltip'>Header Text:<span>Custom header text. If not specified, the header from the spreadsheet will be used.</span></a>" +
				"</label>")
			    .append("<input id='headerText" + i + "' name='headerText" + i + "' type='text' class='headerText short' />"));
						
		$(li).append(ol);
		
		//Insert into DOM.
		$(".horizontal").append(li);
	    }
	}
    }
}
RiseVision.DirectorySettings.prototype.showColorPicker = function(id) {
    gadgets.rpc.call("", "rscmd_openColorPicker", null, id, $("#" + id).val()); 
}
RiseVision.DirectorySettings.prototype.showFontSelector = function(id) {
    gadgets.rpc.call("", "rscmd_openFontSelector", null, id, $("#" + id).data("css"));
}
RiseVision.DirectorySettings.prototype.setColor = function(id, color) {
    $("#" + id).val(color);
    $("#" + id).css("background-color", color);
}
RiseVision.DirectorySettings.prototype.setFont = function(id, css, style) {
    $("#" + id).data("css", css);
    $("#" + id).text(style);
}
RiseVision.DirectorySettings.prototype.getSettings = function() {
    var errorFound = false,
	errors = document.getElementsByClassName("errors")[0],
	nav = $("#nav").val(),
	params = "",
	settings = null;
    
    $(".errors").empty();
    
    //Perform validation.
    errorFound = (directory.settings.validateRequired($("#url"), errors, "Data URL")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#refresh"), errors, "Data Refresh")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#scrollHold"), errors, "Scroll Hold")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#scrollResumes"), errors, "Scroll Resumes")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#rowPadding"), errors, "Row Padding")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#showAll"), errors, "Return to All after x seconds")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#navMargin"), errors, "Margin")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#rowHeight"), errors, "Row Height")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#colPadding"), errors, "Column Padding")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#cardWidth"), errors, "Pop Up Card Width")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#cardTimeout"), errors, "Timeout")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#cardImageWidth"), errors, "Pop Up Card Image Width")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#cardImagePadding"), errors, "Pop Up Card Image Padding")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#cardTitlePadding"), errors, "Title Column Padding")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#cardSubtitlePadding"), errors, "Subtitle Column Padding")) ? true : errorFound;
    errorFound = (directory.settings.validateNumeric($("#cardDetailPadding"), errors, "Detail Column Padding")) ? true : errorFound;
    errorFound = (directory.settings.validateRequired($("#cardLayoutURL"), errors, "Card Layout URL")) ? true : errorFound;
    errorFound = (directory.settings.validateRequired($("#layoutURL"), errors, "Layout URL")) ? true : errorFound;
    
    if (parseInt($("#colCount").val()) > 0) {
	$(".column").each(function(i) {
	    errorFound = (directory.settings.validateRequired($(this), errors, "Column")) ? true : errorFound;
	});
	
	$(".width").each(function(i) {
	    errorFound = (directory.settings.validateNumeric($(this), errors, "Column Width")) ? true : errorFound;
	});
    }
    
    if (errorFound) {
	$(".errors").fadeIn(200).css("display", "inline-block");
	$("#wrapper").scrollTop(0);
	
	return null;
    }
    else {
	//Construct parameters string to pass to RVA.
	params = 
	    "up_url=" + escape($("#url").val()) +
	    "&up_refresh=" + $("#refresh").val() +
	    "&up_imageCol=" + $("#imageCol").val() +
	    "&up_rowColor=" + $("#rowColor").val() +
	    "&up_altRowColor=" + $("#altRowColor").val() +
	    "&up_bgColor=" + $("#bgColor").val() +
	    "&up_rowPadding=" + $("#rowPadding").val() +
	    "&up_nav=" + nav +
	    "&up_showAll=" + $("#showAll").val() +
	    "&up_scrollDirection=" + $("#scrollDirection").val() +
	    "&up_scrollBy=" + $("#scrollBy").val() +    
	    "&up_scrollSpeed=" + $("#scrollSpeed").val() +
	    "&up_scrollResumes=" + $("#scrollResumes").val() +
	    "&up_scrollHold=" + $("#scrollHold").val() +
	    "&up_navMargin=" + $("#navMargin").val() +
	    "&up_navColor=" + $("#navColor").val() +
	    "&up_navBgColor=" + $("#navBgColor").val() +  
	    "&up_headingColor=" + $("#headingColor").val() +
	    "&up_headingBgColor=" + $("#headingBgColor").val() +
	    "&up_headingSortColor=" + $("#headingSortColor").val() +
	    "&up_rowHeight=" + $("#rowHeight").val() +
	    "&up_colPadding=" + $("#colPadding").val() +
	    "&up_colCount=" + $("#colCount").val();
	
	if ($("#showCard").is(":checked")) {
	    params += "&up_showCard=true";
	}
	else {
	    params += "&up_showCard=false";
	}
	
	if ($("#useDefault").is(":checked")) {
	    params += "&up_useDefault=true";
	}
	else {
	    params += "&up_useDefault=false";
	}
	
	params += "&up_layoutURL=" + escape($("#layoutURL").val());
	
	settings = {
	    "params": params,
	    "additionalParams": JSON.stringify(directory.saveAdditionalParams())
	};
    
	$(".errors").css({ display: "none" });
	
	return settings;
    }  
}
RiseVision.DirectorySettings.prototype.saveAdditionalParams = function() {
    var additionalParams = {},
	columns = [],
	nav = $("#nav").val();
    
    additionalParams["heading_font"] = $("#heading_font-style").text();
    additionalParams["heading_font-style"] = $("#heading_font-style").data("css");
    additionalParams["data_font"] = $("#data_font-style").text();
    additionalParams["data_font-style"] = $("#data_font-style").data("css");
    additionalParams["nav_font"] = $("#nav_font-style").text();
    additionalParams["nav_font-style"] = $("#nav_font-style").data("css");
    
    //Save Pop Up Card settings.
    additionalParams["cardLocation"] = $("#cardLocation").val();
    additionalParams["cardWidth"] = $("#cardWidth").val();
    additionalParams["cardTimeout"] = $("#cardTimeout").val();
    
    if ($("#cardBorder").is(":checked")) {
	additionalParams["cardBorder"] = true;
    }
    else {
	additionalParams["cardBorder"] = false;
    }
    
    additionalParams["cardBgColor"] = $("#cardBgColor").val();
    additionalParams["cardImage"] = $("#cardImage").val();
    additionalParams["cardImageAlign"] = $("#cardImageAlign").val();
    additionalParams["cardImageWidth"] = $("#cardImageWidth").val();
    additionalParams["cardImagePadding"] = $("#cardImagePadding").val();
    additionalParams["closeBorderColor"] = $("#closeBorderColor").val();
    additionalParams["closeFillColor"] = $("#closeFillColor").val();
    additionalParams["cardTitle"] = $("#cardTitle").val();
    additionalParams["cardTitle_font"] = $("#cardTitle_font-style").text();
    additionalParams["cardTitle_font-style"] = $("#cardTitle_font-style").data("css");	    
    additionalParams["cardTitlePadding"] = $("#cardTitlePadding").val();
    additionalParams["cardSubtitle"] = $("#cardSubtitle").val();
    additionalParams["cardSubtitle_font"] = $("#cardSubtitle_font-style").text();
    additionalParams["cardSubtitle_font-style"] = $("#cardSubtitle_font-style").data("css");
    additionalParams["cardSubtitlePadding"] = $("#cardSubtitlePadding").val();
    additionalParams["cardDetail"] = $("#cardDetail").val();
    additionalParams["cardDetail_font"] = $("#cardDetail_font-style").text();
    additionalParams["cardDetail_font-style"] = $("#cardDetail_font-style").data("css");
    additionalParams["cardDetailPadding"] = $("#cardDetailPadding").val();
    
    if ($("#cardUseDefault").is(":checked")) {
	additionalParams["cardUseDefault"] = true;
    }
    else {
	additionalParams["cardUseDefault"] = false;
    }
    
    additionalParams["cardLayoutURL"] = $("#cardLayoutURL").val();
    
    for (var i = 0; i < parseInt($("#colCount").val()); i++) {
	columns.push(directory.saveFormatSettings(i + 1, columns));
    }
    
    additionalParams["columns"] = columns;
    
   return additionalParams;
}
RiseVision.DirectorySettings.prototype.saveFormatSettings = function(i) {
    return {
	"column": $("#column" + i).val(),
	"alignment": $("#alignment" + i).val(),
	"width": $("#width" + i).val(),
	"header": $("#headerText" + i).val()
    };
}
/* Settings End */

/* Functionality Start */
RiseVision.Directory = function() {
    this.url = prefs.getString("url");
    this.refresh = prefs.getInt("refresh");
    this.imageCol = prefs.getString("imageCol").toUpperCase();
    this.rowPadding = prefs.getInt("rowPadding") / 2 + "px";
    this.colPadding = prefs.getInt("colPadding") / 2 + "px";
    this.nav = prefs.getString("nav");
    this.showAll = prefs.getInt("showAll") * 1000;
    this.useDefault = prefs.getBool("useDefault");
    
    if (this.useDefault) {
	this.layoutURL = "";
    }
    else {	
	this.layoutURL = prefs.getString("layoutURL");
    }
    
    this.imageIndex = -1;
    this.cardImageIndex = -1;
    this.cardTitleIndex = -1;
    this.cardSubtitleIndex = -1;
    this.cardDetailIndex = -1;
    this.imageTotal = 0;
    this.isLoading = true;
    this.isSwiping = false;
    this.isTable = false;
    this.column = "A";
    this.columns = {};
    this.sortIndex = 0;
    this.sortDirection = "asc";
    this.sortConfig = {	
	"bDestroy": true,
	"bFilter": false,
	"bInfo": false,
	"bLengthChange": false,
	"bPaginate": false,
	"sScrollY": "500px"	//Needed just to force table structure conducive to sorting.
    };
    
    this.viz = new RiseVision.Common.Visualization();
}
RiseVision.Directory.prototype.getAdditionalParams = function(name, value) {
    if (name == "additionalParams") {
	if (value) {
	    var styleNode = document.createElement("style");
	    
	    value = JSON.parse(value);
	    
	    //Inject CSS font styles into the DOM.
	    styleNode.appendChild(document.createTextNode(value["heading_font-style"]));
	    styleNode.appendChild(document.createTextNode(value["data_font-style"]));
	    styleNode.appendChild(document.createTextNode(value["nav_font-style"]));
	    styleNode.appendChild(document.createTextNode(value["cardTitle_font-style"]));
	    styleNode.appendChild(document.createTextNode(value["cardSubtitle_font-style"]));
	    styleNode.appendChild(document.createTextNode(value["cardDetail_font-style"]));	    
	    styleNode.appendChild(document.createTextNode("#nav ul li a:active, #nav ul li a:visited" + value["nav_font-style"]));	    
	    document.getElementsByTagName("head")[0].appendChild(styleNode);
	    
	    //Save other parameters in variables so that they can be used later.
	    directory.columns = value.columns;
	    directory.cardLocation = value.cardLocation;
	    directory.cardWidth = value.cardWidth;
	    directory.cardTimeout = value.cardTimeout * 1000;
	    directory.cardBorder = value.cardBorder;
	    directory.cardBgColor = value.cardBgColor;
	    
	    if (value.cardImage) {
		directory.cardImage = value.cardImage.toUpperCase();
	    }
	    
	    directory.cardImageAlign = value.cardImageAlign;
	    directory.cardImageWidth = value.cardImageWidth;
	    directory.cardImagePadding = value.cardImagePadding;
	    
	    directory.closeBorderColor = value.closeBorderColor;
	    directory.closeFillColor = value.closeFillColor;
	    
	    if (value.cardTitle) {
		directory.cardTitle = value.cardTitle.toUpperCase();
	    }
	    
	    directory.cardTitlePadding = value.cardTitlePadding;
	    
	    if (value.cardSubtitle) {
		directory.cardSubtitle = value.cardSubtitle.toUpperCase();
	    }
	    
	    directory.cardSubtitlePadding = value.cardSubtitlePadding;
	    
	    if (value.cardDetail) {
		directory.cardDetail = value.cardDetail.toUpperCase();
	    }
	    
	    directory.cardDetailPadding = value.cardDetailPadding;
	    directory.cardUseDefault = value.cardUseDefault;
	    directory.cardLayoutURL = value.cardLayoutURL;
	}
    }
    
    directory.init();
}
//Load the layout and CSS files.
RiseVision.Directory.prototype.init = function() {
    var self = this,
	params = {},
	link = document.createElement("link");
    
    if (this.useDefault) {
	if (this.isVerticalLayout()) {
	    RiseVision.Common.Utility.loadCSS("http://4e00310b254f742d8e8a-f5265e07f44a3daeee32044cdfaf29ee.r22.cf2.rackcdn.com/css/Vertical.css");
	}
	//Horizontal layout
	else {
	    RiseVision.Common.Utility.loadCSS("http://4e00310b254f742d8e8a-f5265e07f44a3daeee32044cdfaf29ee.r22.cf2.rackcdn.com/css/Horizontal.css");
	}
	
	if (self.cardUseDefault) {
	    self.getListings("all");
	}	    
	else {
	    self.loadCustomCard();
	}	
    }
    else {
	//Load custom layout.
	params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
	gadgets.io.makeRequest(this.layoutURL, function(obj) {
	    var data = obj.data;
	    
	    if (data.getElementsByTagName("Style").length > 0) {
		var head = document.getElementsByTagName("head")[0],
		    style = document.createElement("style");
		    
		style.type = "text/css";
		style.innerHTML = data.getElementsByTagName("Style")[0].childNodes[1].nodeValue;
		head.appendChild(style);
	    }
	    
	    self.directory = data.getElementsByTagName("Layout")[0].childNodes[1].nodeValue;
	    
	    if (self.cardUseDefault) {
		self.getListings("all");
	    }	    
	    else {
		self.loadCustomCard();
	    }	    
	}, params);
    }
}
//Load custom layout for the Pop Up Card.
RiseVision.Directory.prototype.loadCustomCard = function() {
    var params = {},
	self = this;
	
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.DOM;
    gadgets.io.makeRequest(this.cardLayoutURL, function(obj) {
	var data = obj.data;
	
	if (data.getElementsByTagName("Style").length > 0) {
	    var head = document.getElementsByTagName("head")[0],
		style = document.createElement("style");
		
	    style.type = "text/css";
	    style.innerHTML = data.getElementsByTagName("Style")[0].childNodes[1].nodeValue;
	    head.appendChild(style);
	}
	
	//Remove UI for default card and append custom card UI instead..
	$("#card.default").remove();
	$("#container").append(data.getElementsByTagName("Layout")[0].childNodes[1].nodeValue);
	self.getListings("all");	    
    }, params);
}
RiseVision.Directory.prototype.configureNavigation = function($element) {
    var self = this;
    
    $element.alphaNav({
	position: prefs.getString("nav"),
	margin: prefs.getInt("navMargin"),
	selectedColor: prefs.getString("navColor"),
	selectedBackground: prefs.getString("navBgColor"),
	onclick: function(letter) {
	    self.onAlphaNavClicked(letter);
	}
    })    
}
RiseVision.Directory.prototype.onAlphaNavClicked = function(letter) {
    clearTimeout(this.showAllTimer);
	    
    //Remember the sort column and direction.
    if (this.isTable) {		
	var sortColumn = null;
	
	//Get the column that has been sorted.
	if ($(".sorting_asc").length != 0) {
	    sortColumn = $(".sorting_asc");
	    this.sortDirection = "asc";
	}
	else if ($(".sorting_desc").length != 0) {
	    sortColumn = $(".sorting_desc");
	    this.sortDirection = "desc";
	}

	//Get the index of the column that has been sorted.
	if (sortColumn && sortColumn.length > 0) {
	    if ($(".dataTables_scrollHead th").index($(".sorting_asc")) >= 0) {
		this.sortIndex = $(".dataTables_scrollHead th").index($(".sorting_asc"));
	    }
	    else {
		this.sortIndex = $(".dataTables_scrollHead th").index($(".sorting_desc"));
	    }
	}		
    }
    
    this.getListings(letter);
}
RiseVision.Directory.prototype.getListings = function(letter) {
    var self = this,
	queryString = "select *",
	settings = null;
	
    //Gadget Issue 671 - Temporarily size the Gadget using the UserPrefs.
    $("#container").width(prefs.getString("rsW"));
    $("#container").height(prefs.getString("rsH"));
    
    if ((letter != "all") && (this.nav != "none")) {
	if (this.isTable && this.hasHeadings()) {
	    //The navigation applies to the currently selected column.
	    if ($(".dataTables_scrollHeadInner .sorting_asc").length == 1) {
		this.column = $(".dataTables_scrollHeadInner .sorting_asc").attr("id");
	    }
	    else if ($(".dataTables_scrollHeadInner .sorting_desc").length == 1) {
		this.column = $(".dataTables_scrollHeadInner .sorting_desc").attr("id");
	    }
	}
	
	//Case insensitive search.
	queryString = queryString + " where " + this.column + " starts with upper('" + letter + "') or " + this.column + " starts with lower('" + letter + "')";
    }
    
    settings = {
	url: this.url,
	refreshInterval: this.refresh,
	queryString: queryString,
	callback: function(data) {
	    var numRows = data.getNumberOfRows(),
		numCols = data.getNumberOfColumns(),
		col = 0;
	    
	    self.data = data;
	    self.imagesLoaded = 0;
	    self.cols = [];	    
	    
	    //Display a message if no data was found.
	    if (numRows == 0) {
		$("#scrollContainer").infiniteScroll.stop();
		$("#scrollContainer").empty();
		$("#scrollContainer").append("<div class='noData'>No matching records found</div>");		
		
		if (self.isLoading) {
		    readyEvent();
		}
		else {
		    self.startShowAllTimer();
		}
	    }
	    else {
		for (; col < numCols; col++) {
		    self.cols.push(data.getColumnId(col));
		}
		
		//Save index of image column and indices of columns used by the card.	
		for (col = 0; col < numCols; col++) {
		    if (self.imageCol) {
			if (data.getColumnId(col) == self.imageCol) {
			    self.imageIndex = col;
			    break;
			}
		    }
		}
		
		if (prefs.getBool("showCard")) {
		    if (self.cardImage) {
			for (col = 0; col < numCols; col++) {   		    			
			    if (data.getColumnId(col) == self.cardImage) {
				self.cardImageIndex = col;
				break;
			    }
			}
		    }
		    
		    if (self.cardTitle) {
			for (col = 0; col < numCols; col++) {   		    			
			    if (data.getColumnId(col) == self.cardTitle) {
				self.cardTitleIndex = col;
				break;
			    }
			}
		    }
		    
		    if (self.cardSubtitle) {
			for (col = 0; col < numCols; col++) {   		    			
			    if (data.getColumnId(col) == self.cardSubtitle) {
				self.cardSubtitleIndex = col;
				break;
			    }
			}
		    }
		
		    if (self.cardDetail) {    
			for (col = 0; col < numCols; col++) {   		    			
			    if (data.getColumnId(col) == self.cardDetail) {
				self.cardDetailIndex = col;
				break;
			    }
			}
		    }
		}
		
		self.hasImage = self.imageIndex == -1 ? false: true;
		
		if (self.hasImage) {
		    //Only one image allowed per row.
		    self.imageTotal = numRows;
		}
		
		if (self.isLoading && self.hasImage) {
		    if (self.useDefault) {
			//Image column can't be sorted. Since image is the first column in a default layout, put the default sort index on the next column.
			self.sortIndex = 1;
		    }
		    else {
			//Figure out what the first column is that is not the image column.
			self.sortIndex = self.imageIndex == 0 ? 1 : self.imageIndex - 1;
		    }
		}
		
		//Hide to avoid flickering while UI is being recreated.
		$("#scrollContainer").hide();		
	    
		if (self.useDefault) {
		    if (self.isVerticalLayout()) {
			self.buildVerticalLayout.call(self);
		    }
		    else {
			self.buildHorizontalLayout.call(self);
		    }
		}
		//Custom layout.
		else {
		    self.showCustomLayout.call(self);
		}
	    }
	}
    };
    
    //getFilteredData(settings);
    this.viz.getData(settings);
}
RiseVision.Directory.prototype.buildVerticalLayout = function() {
    var page = document.createElement("ul"),
	numRows = this.data.getNumberOfRows(),
	numCols = this.data.getNumberOfColumns(),
	isFirstTextCol = true,
	self = this;
	
    page.setAttribute("class", "page");
        
    //Remove old content.
    if (!this.isLoading) {
	$("#scrollContainer").infiniteScroll.stop();
	$("#scrollContainer").empty();
    }
    
    $("#scrollContainer").append(page);		
	
    for (var row = 0; row < numRows; row++) {
	$(".page").append("<li class='listing item'><div class='content'></div></li>");
	$(".listing:last").data("row", row);
	
	for (var col = 0; col < numCols; col++) {
	    if (this.showColumn(col)) {
		//Add text first because the height of the content will be used to set the height of the image.
		if (col != this.imageIndex) {
		    if (isFirstTextCol) {
			if (this.data.getFormattedValue(row, col)) {
			    $(".content:last").append("<p class='heading_font-style'>" + this.data.getFormattedValue(row, col) + "</p>");
			}
			
			isFirstTextCol = false;
		    }		
		    else {
			if (this.data.getFormattedValue(row, col)) {
			    $(".content:last").append("<span class='data_font-style'>" + this.data.getFormattedValue(row, col) + "</span><br />");
			}
		    }
		}		
	    }
	    
	    //Add horizontal line after last column and then add the image.
	    if (col == numCols - 1) {
		$(".listing:last").append("<hr>");
		isFirstTextCol = true;		
		
		if (this.hasImage) {
		    this.loadImage(row, this.imageIndex, this.onImageLoaded, this.onImageError);
		}		    
	    }
	}
    }	
    
    //No images to load.
    if (!this.hasImage) {
	$(".content").css("margin-left", "0%");
	this.initDirectory();
    } 
}
RiseVision.Directory.prototype.buildHorizontalLayout = function() {
    var table = document.createElement("table"),
	numRows = this.data.getNumberOfRows(),
	numCols = this.data.getNumberOfColumns(),
	images = [];
    
    this.isTable = true;
    
    table.setAttribute("id", "directory");
    table.setAttribute("class", "page");
    
    //Remove old content.
    if (!this.isLoading) {
	$(".dataTables_scrollBody").infiniteScroll.stop();
	$("#scrollContainer").empty();
	$("#nav").hide();
    }
    
    $("#scrollContainer").append(table);       
    
    //Add rows.
    for (var row = 0; row < numRows; row++) {
	this.renderRow(row);
    }
    
    //Add headings.
    if (numCols > 0) {
	this.renderHeadings(true);
    }
    
    if (this.hasImage) {		
	if (this.imageTotal > 0) {
	    for (var row = 0; row < numRows; row++) {
		this.loadImage(row, this.imageIndex, this.onBgImageLoaded, this.onBgImageError);
	    }
	}
	else {	//No rows
	    this.initTable();
	}
    }
    else {
	this.initTable();
    }
}
RiseVision.Directory.prototype.showCustomLayout = function() {
    var numRows = this.data.getNumberOfRows(),
	numCols = this.data.getNumberOfColumns(),
	self = this,
	$listing;
	    
    //Remove old content.
    if (!this.isLoading) {	
	$("#scrollContainer").infiniteScroll.stop();
	$("#scrollContainer").empty();	
    }
    
    //Add the layout.
    $("#scrollContainer").append(this.directory);
    $listing = $(".listing");
    this.isTable = $("#scrollContainer").find("table#directory").length > 0 ? true : false;
	
    //One listing has already been added, so add new listings for each row less one.
    for (var row = 1; row < numRows; row++) {
	$(".listing:last").after($listing.clone());
    }
    
    //Add headings.
    if (this.isTable) {
	this.renderHeadings(false);
    }
	
    for (var row = 0; row < numRows; row++) {
	$(".listing").eq(row).data("row", row);
	
	for (var col = 0; col < numCols; col++) {
	    var $cell = $("." + this.cols[col]).eq(row);
			    
	    if ($cell.length > 0) {
		//Add text first because the height of the content will be used to set the height of the image.
		if (col != this.imageIndex) {
		    $cell.html(this.data.getFormattedValue(row, col));
		}		    
	    }		
	    
	    //Load the image after all of the text has been populated.
	    if (col == numCols - 1) {
		if (this.hasImage) {
		    if (this.isTable) {
			this.loadImage(row, this.imageIndex, this.onBgImageLoaded, this.onBgImageError);
		    }
		    else {
			this.loadImage(row, this.imageIndex, this.onImageLoaded, this.onImageError);
		    }
		}
	    }
	}
    }
    
    if (this.imageTotal == 0) {
	if (this.isTable) {
	    this.initTable();
	}
	else {
	    this.initDirectory();
	}	
    }     
}
RiseVision.Directory.prototype.configureCard = function() {
    var self = this,
	width = this.cardWidth / prefs.getInt("rsW") * 100 + "%",
	imageWidth = this.cardImageWidth,
	radius = $("#close").width() / 2 + "em";
    
    if (prefs.getBool("showCard")) {
	if (this.isLoading) {
	    //Card
	    $("#card").css("width", width);
	    $("#card").css("background-color", this.cardBgColor);
	    
	    if (this.cardBorder) {
		$("#card").addClass("cardBorder");
	    }
	    
	    //Card image
	    if (this.cardImageAlign == "topRight") {
		$("#image").addClass("right");
	    }
	    else if (this.cardImageAlign == "topLeft") {
		$("#image").addClass("left");
	    }
	    else {
		$("#image").addClass("center");
	    }
	    
	    $("#image").css("padding", this.cardImagePadding);
	    
	    if (this.cardImageIndex != -1) {
		imageWidth = imageWidth / $("#card").outerWidth(true) * 100 + "%";
		
		if (this.cardImageAlign != "center") {
		    $("#image").css("width", imageWidth);
		}
	    }
	    
	    //Close button
	    $("#close").css("color", this.closeBorderColor);
	    $("#close").css("background-color", this.closeFillColor);
	    $("#close").css("border-color", this.closeBorderColor);
	    $("#close").css({
		"-webkit-border-radius": radius,
		"-moz-border-radius": radius,
		"border-radius": radius
	    });
	    
	    $("#close").on("click", function() {
		clearTimeout(self.cardCloseTimer);
		$("#card").bPopup().close();
		
		return false;
	    });
	    
	    //Content
	    $("#title").css("padding", this.cardTitlePadding);
	    $("#subtitle").css("padding", this.cardSubtitlePadding);
	    $("#detail").css("padding", this.cardDetailPadding);
	}    
	
	$(".listing").on("click", function(e) {
	    var row = $(this).data("row");	    
	    
	    if (!self.isSwiping) {
		if (row >= 0) {		
		    if (self.cardTitleIndex != -1) {
			$("#title").html(self.data.getFormattedValue(row, self.cardTitleIndex));
		    }
		    
		    if (self.cardSubtitleIndex != -1) {
			$("#subtitle").html(self.data.getFormattedValue(row, self.cardSubtitleIndex));
		    }
		    
		    if (self.cardDetailIndex != -1) {
			$("#detail").html(self.data.getFormattedValue(row, self.cardDetailIndex));
		    }
		    
		    if (self.cardImageIndex != -1) {
			self.loadImage(row, self.cardImageIndex, function(row, img) {
			    $("#image").empty();
			    $("#image").append(img);
			    
			    if (self.cardImageAlign == "center") {
				$("#image > img").css("width", imageWidth);
			    }
			    
			    self.showCard();
			}, function() {
			    $("#image").empty();
			    self.showCard();
			});
		    }
		    else {
			self.showCard();
		    }
		}
	    }
	    else {
		self.isSwiping = false;
	    }
	});
    }
}
RiseVision.Directory.prototype.showCard = function() {
    var settings = { modalClose: false },
	hPos = 0,
	vPos = 0;
	    
    if (this.cardLocation == "left") {
	settings.position = [hPos, "auto"];
    }
    else if (this.cardLocation == "right") {
	hPos = prefs.getInt("rsW") - $("#card").outerWidth(true);
	settings.position = [hPos, "auto"];
    }
    else if (this.cardLocation == "top") {
	settings.position = ["auto", vPos];
    }
    else if (this.cardLocation == "bottom") {
	vPos = prefs.getInt("rsH") - $("#card").outerHeight(true);
	settings.position = ["auto", vPos];
    }
    else {
	//Center is default position. 
    }
    
    $("#card").bPopup(settings);
    
    this.cardCloseTimer = setTimeout(function() {
	$("#card").bPopup().close();
    }, this.cardTimeout);
}
RiseVision.Directory.prototype.renderHeadings = function(exclude) {
    var tr = document.createElement("tr"),
	hasHeadings = this.hasHeadings(),
	numCols = this.data.getNumberOfColumns();
    
    for (var col = 0; col < numCols; col++) {	
	var th = document.createElement("th");
	
	//Don't render table headings for data that doesn't have any headings, or for data that already appears on the Pop Up card.
	//Also, only create a heading if this column exists in the layout (might not for a custom layout where a column has been removed).
	if (hasHeadings) {
	    if ((!exclude || (exclude && this.showColumn(col))) && ($("." + this.cols[col]).length > 0)) {
		th.setAttribute("id", this.data.getColumnId(col));
		th.setAttribute("class", "nowrap heading_font-style");
		$(th).html(this.data.getColumnLabel(col));
	    
		//No sort indicator for the image column.
		if (this.hasImage && col == this.imageIndex) {
		    if (this.useDefault) {
			$(tr).prepend(th);
		    }
		    else {
			$(tr).append(th);
		    }
		}
		else {
		    var arrow = document.createElement("div"),
			indicator = document.createElement("div"),
			indicator1 = document.createElement("div"),
			indicator2 = document.createElement("div");
			
		    arrow.setAttribute("class", "arrow");
		    indicator.setAttribute("class", "indicator");
		    indicator1.setAttribute("class", "indicator1");
		    indicator2.setAttribute("class", "indicator2");
		    
		    if (this.sortDirection == "asc") {
			$(arrow).html("&darr;");
			$(indicator1).html("A");
			$(indicator2).html("Z");
		    }
		    else {
			$(arrow).html("&uarr;");
			$(indicator1).html("Z");
			$(indicator2).html("A");
		    }
		    
		    $(th).append(arrow);
		    $(indicator).append(indicator1);
		    $(indicator).append(indicator2);
		    $(th).append(indicator);
		    $(tr).append(th);
		}
	    }
	}
	else {
	    if (this.showColumn(col)) {
		$(tr).append(th);
	    }
	}
    }
    
    $("table").prepend($("<thead>").append(tr));
}
RiseVision.Directory.prototype.hasHeadings = function() {
    var hasHeading = false,
	numCols = this.data.getNumberOfColumns();
    
    for (var col = 0; col < numCols; col++) {
	var label = this.data.getColumnLabel(col);
	
	if (label) {
	    hasHeading = true;
	    break;
	}
    }
    
    return hasHeading;
}
//Render each row of data.
RiseVision.Directory.prototype.renderRow = function(row) {
    var tr = document.createElement("tr"),
	numCols = this.data.getNumberOfColumns();
    
    tr.setAttribute("class", "listing item");
    $(tr).data("row", row);
    
    for (var col = 0; col < numCols; col++) {
	if (this.showColumn(col)) {
	    var value = "", style = "";
	
	    value = this.data.getFormattedValue(row, col);
	    style = this.data.getProperty(row, col, "style");
	    
	    //Strip out the font-family that holds an incorrect value.
	    if (style) {
		style = style.substring(0, style.indexOf("font-family:"));
	    }
	    
	    if (this.hasImage && col == this.imageIndex) {
		this.addImage(tr, this.cols[col]);
	    }
	    else {
		this.addCell(tr, value, style, this.cols[col]);
	    }
	}
    }

    $("table").append(tr);
}
RiseVision.Directory.prototype.addImage = function(tr, className) {
    var td = document.createElement("td");
    
    td.setAttribute("class", className + " image");
    $(tr).prepend(td);
}
RiseVision.Directory.prototype.addCell = function(tr, value, style, className) {
    var td = document.createElement("td");
    
    if (style) {
	td.setAttribute("style", style);
    }
    
    td.setAttribute("class", className + " data_font-style");
    $(td).html(value);
    $(tr).append(td);
}
RiseVision.Directory.prototype.loadImage = function(row, imageIndex, onLoadCallback, onErrorCallback) {    
   var self = this,
	img = new Image();
    
    img.onload = function() {
	if (onLoadCallback) {
	    onLoadCallback.call(self, row, this);
	}
    }
    img.onerror = function() {
	if (onErrorCallback) {
	    onErrorCallback.call(self, row, this);
	}
    }
    
    img.src = this.data.getFormattedValue(row, imageIndex);
}
RiseVision.Directory.prototype.onImageLoaded = function(row, img) {
    var div = document.createElement("div");

    div.setAttribute("class", "image");    
     
    $(div).css({
	"background": "url(" + this.data.getFormattedValue(row, this.imageIndex) + ") center center no-repeat"
    });
    
    $(".listing").eq(row).prepend(div);
    
    this.onAllImagesLoaded();
}
RiseVision.Directory.prototype.onImageError = function(row, img) {
    var div = document.createElement("div");
    
    div.setAttribute("class", "image");
    $(".listing").eq(row).prepend(div);
    
    this.onAllImagesLoaded();
}
RiseVision.Directory.prototype.onAllImagesLoaded = function() {
    var self = this;
    
    this.imagesLoaded++;
    
    if (this.imagesLoaded == this.imageTotal) {
	this.initDirectory();
    }
}
RiseVision.Directory.prototype.initDirectory = function() {
    var $img = null,
	self = this;
    
    $("#scrollContainer").show();
    
    $(".content").css({
	"padding-top": this.rowPadding,
	"padding-bottom": this.rowPadding
    });
    
    $(".listing:odd").addClass("odd");
    $(".listing:even").addClass("even");
    
    //On initial load, this functionality is taken care of by play().
    if (!this.isLoading) {
	$(".listing").each(function(index) {
	    $(".image").eq(index).css("height", $(".listing").eq(index).height());
	});
	
	//Need to use margins with background images and not padding.
	$(".image").css({
	    "margin-top": this.rowPadding,
	    "margin-bottom": this.rowPadding
	});
    }
    
    $("#scrollContainer").infiniteScroll({
	scrollBy: prefs.getString("scrollBy"),
	direction: prefs.getString("scrollDirection"),
	duration: prefs.getInt("scrollHold") * 1000,
	speed: prefs.getString("scrollSpeed"),
	swipingTimeout: prefs.getInt("scrollResumes") * 1000
    })
    .bind("onSwipe", function(event) {
	self.isSwiping = true;
    });
    
    this.configureCard();
    
    //Size container back to its original dimensions.
    $("#container").width("100%");
    $("#container").height("100%");
    
    if (this.isLoading) {	   
	this.configureNavigation($("#container"));	
	readyEvent();
    }
    else {
	$("#scrollContainer").infiniteScroll.start();
	this.startShowAllTimer();
    }
}
//Move this functionality to AlphaNav.js instead.
RiseVision.Directory.prototype.startShowAllTimer = function() {
    var self = this;
    
    if ($("#nav ul li.selected").attr("id") != "all") {
	if (this.showAll) {
	    this.showAllTimer = setTimeout(function() { 
		$("#nav ul li.selected a").css({
		    "background": "",
		    "-webkit-border-radius": "",
		    "-moz-border-radius": "",
		    "border-radius": ""
		});
		$("#nav ul li.selected a").css("color", "");
		$("#nav ul li.selected").removeClass("selected");
		$("#nav ul li#all").addClass("selected");
		
		var radius = $("#nav ul li a").width() / 2 + "em";

		$("#nav ul li.selected a").css({
		    "background": prefs.getString("navBgColor"),
		    "-webkit-border-radius": radius,
		    "-moz-border-radius": radius,
		    "border-radius": radius
		});
		$("#nav ul li.selected a").css("color", prefs.getString("navColor"));
	
		self.onAlphaNavClicked("all");
	    }, this.showAll);
	}
    }
}
RiseVision.Directory.prototype.onBgImageLoaded = function(row) {
    var $image = $(".listing").eq(row).find(".image"),
	$img = $("<img>");    
	
    if ($image.length > 0) {
	$img.attr("src", this.data.getFormattedValue(row, this.imageIndex));
	$img.height(0);
	$image.append($img);
    }
    
    this.onAllBackgroundImagesLoaded();
}
RiseVision.Directory.prototype.onBgImageError = function() {
    this.onAllBackgroundImagesLoaded();
}
RiseVision.Directory.prototype.onAllBackgroundImagesLoaded = function() {
    var self = this;
    
    this.imagesLoaded++;
    
    if (this.imagesLoaded == this.imageTotal) {	
	this.initTable();
    }
}      
RiseVision.Directory.prototype.loadCardImage = function() {
    var numRows = this.data.getNumberOfRows();
    
    for (var row = 0; row < numRows; row++) {
	this.loadImage(row, this.cardImageIndex);
    }	
}
RiseVision.Directory.prototype.initTable = function() {
    var self = this,
	colIndex, maxHeight;
	
    this.formatColumns($("th"));
    
    //Logo column is not sortable.
    if (this.hasImage) {
	if (this.useDefault) {
	    this.sortConfig.aoColumnDefs = [{"bSortable": false, "aTargets": [0]}];
	}
	//Image in custom layout can be shown in any column.
	else {
	    this.sortConfig.aoColumnDefs = [{"bSortable": false, "aTargets": [this.imageIndex]}];
	}
    }
    else {
	this.sortConfig.aoColumnDefs = [];
    }
    
    //Use oSettings.aoColumns.sWidth for datatables to size columns.
    $.each(this.columns, function(index, value) {
	if (value.width) {
	    colIndex = $("." + value.column + ":first").parent().children().index($("." + value.column + ":first"));
	    
	    self.sortConfig.aoColumnDefs.push({
		"sWidth": value.width,
		"aTargets": [colIndex]
	    });
	}
    });
    
    this.sortConfig.aaSorting = [[this.sortIndex, this.sortDirection]];
    
    $("#scrollContainer").show();
    $("#nav").show();
    
    //Find the maximum height of all images. 
    maxHeight = Math.max.apply(null, $(".image").map(function () {
	return $(this).height();
    }).get());
    
    //Set the height of the images now that we know maxHeight.
    $(".image img").height(maxHeight);
    
    $("#directory").dataTable(this.sortConfig);	//TODO: Change this to table to remove dependency on id.
    
    if (!this.hasHeadings()) {
	$(".dataTables_wrapper table thead").css("display", "none");
    }
    
    $(".dataTables_scrollHead table thead tr, .dataTables_scrollBody table tbody tr").height(prefs.getInt("rowHeight"));
    
    //Add padding. No need to calculate as a percentage since it will work out to be the same result every time.
    $(".dataTables_scrollHead table thead tr th, td").css({
	"padding-top": this.rowPadding,
	"padding-bottom": this.rowPadding
    });
    
    $("table thead tr th, td").css({ 
	"padding-left": this.colPadding,
	"padding-right": this.colPadding
    });
    
    //First cell shouldn't have any padding in front of it.
    $("table tr th:first-child, td:first-child").css({
	"padding-left": "10px"
    });
    
    //Last cell shouldn't have any padding after it.
    $("table tr th:last-child, td:last-child").css({
	"padding-right": "10px"
    });    
    
    this.configureCard();
	
    if (this.isLoading) {	
	this.configureNavigation($("#container"));
    }
    
    if (this.isVerticalLayout()) {
	$(".dataTables_scrollBody").height($("#container").outerHeight(true) - $(".dataTables_scrollHead").height());
    }
    else {
	$("#scrollContainer").height($("#container").outerHeight(true) - $("#nav").outerHeight(true));
	$(".dataTables_scrollBody").height($("#container").outerHeight(true) - $("#nav").outerHeight(true) - $(".dataTables_scrollHead").height());
    }
    
    $(".dataTables_scrollBody").infiniteScroll({
	scrollBy: prefs.getString("scrollBy"),
	direction: prefs.getString("scrollDirection"),
	duration: prefs.getInt("scrollHold") * 1000,
	speed: prefs.getString("scrollSpeed"),
	swipingTimeout: prefs.getInt("scrollResumes") * 1000
    })
    .bind("onSwipe", function(event) {
	self.isSwiping = true;
    });
    
    //Size container back to its original dimensions.
    $("#container").width("100%");
    $("#container").height("100%");
	
    if (this.isLoading) {
	readyEvent();
    }
    else {
	$(".dataTables_scrollBody").infiniteScroll.start();	
	this.startShowAllTimer();
    }
}
/* Format each column. */
RiseVision.Directory.prototype.formatColumns = function($elem) {
    var self = this;
    
    $.each(this.columns, function(index, value) {
	if (value.column) {
	    var $columns = $("." + value.column),
		colIndex = $("." + value.column + ":first").parent().children().index($("." + value.column + ":first")),
		width;
	    
	    if ($columns.length > 0) {
		//Header Text
		if (value.header) {
		    $elem.eq(colIndex).html(value.header);
		}
		
		if (self.isLoading && value.width) {
		    width = parseInt(value.width);
		    width = width / prefs.getInt("rsW") * 100 + "%";
		    value.width = width;
		}
		
		if (self.hasImage && colIndex == 0) {
		    $columns.find("div").css("background-position", value.alignment);
		}
		else {
		    $columns.css("text-align", value.alignment);
		}
		
		$elem.eq(colIndex).css("text-align", value.alignment);		
	    }
	}
    }); 
}
RiseVision.Directory.prototype.showColumn = function(col) {
    return (col != this.cardTitleIndex) && (col != this.cardSubtitleIndex) && (col != this.cardDetailIndex) && (col != this.cardImageIndex)
}
//Set a timer that will expire if there is no user interaction.
RiseVision.Directory.prototype.setTimer = function() {
    var self = this;
    
    $.idleTimer(60000);
    $(document).bind("idle.idleTimer", function() {
	$.idleTimer("destroy");
	self.showTab(self.tabIDs[0]);	//Go to Today.
    });
}
RiseVision.Directory.prototype.isVerticalLayout = function() {
    return (this.nav == "left") || (this.nav == "right");
}
RiseVision.Directory.prototype.play = function() {
    //The height of the listing is only correct after the Gadget is visible.
    if (this.isLoading && this.isVerticalLayout() && !this.isTable) {
	$(".listing").each(function(index) {
	    $(".image").eq(index).css("height", $(".listing").eq(index).height());
	});
	
	//Need to use margins with background images and not padding.
	$(".image").css({
	    "margin-top": this.rowPadding,
	    "margin-bottom": this.rowPadding
	});
    }
    
    this.isLoading = false;
    
    if (this.isTable) {
	$(".dataTables_scrollBody").infiniteScroll.start();	
    }
    else {
	$("#scrollContainer").infiniteScroll.start();
    }    
}
RiseVision.Directory.prototype.pause = function() {
    if (this.isTable) {
	$(".dataTables_scrollBody").infiniteScroll.pause();
    }
    else {
	$("#scrollContainer").infiniteScroll.pause();	
    }
}